package InventurServer;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Listener implements Runnable {

	private Socket clientSocket = null;
	private String teamID = "";
	private static int hash;
	private static FileWriter fwFile;
	private DataInputStream dataInputStream = null;
	private DataOutputStream dataOutputStream = null;

	public static void main(String[] args) {
		ServerSocket sSocket = null;
		String of = "";
		int p = 0;
		int h = 0;
		if (args.length == 3) {
			try {
				p = Integer.parseInt(args[0]);
				h = Integer.parseInt(args[1]);
			} catch (NumberFormatException e) {
				System.err.println("Arguments port and hash must be integers");
				System.exit(1);
			}
			of = args[2] + ".csv";
			try {
				sSocket = new ServerSocket(p);
				if (sSocket != null) {
					System.out.println("Server started. Listening on port " + p);
					try {
						fwFile = new FileWriter(of, true);
					} catch (IOException e) {
						e.printStackTrace();
					}
					while (true) {
						Socket cSocket = sSocket.accept();
						Listener con = new Listener(cSocket, p, h);
						Thread t = new Thread(con);
						t.start();
					}
				}
			} catch (IOException e) {
				System.out.println("Could not listen on port " + p);
			} finally {
				if (sSocket != null) {
					try {
						sSocket.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		} else {
			System.out.println("InventurServer usage:");
			System.out.println("\tjava -jar inventurserver.jar port hash outfile");
			System.out.println("\t\tport - number from 49152 to 65536");
			System.out.println("\t\thash - digit sum modulo 10");
			System.out.println("\t\toutfile - filename of csv-file (w/o .csv-extension)");
			System.out.println("Example");
			System.out.println("\tjava -jar inventurserver 55555 7 inv2013");
		}
	}

	public Listener(Socket cs, int p, int h) {
		clientSocket = cs;
		teamID = "";
		hash = h;
		System.out.println("Connected to ip " + clientSocket.getInetAddress().getHostAddress() + " : " + clientSocket.getPort());
	}

	public void run() {
		String datablock = null;
		try {
			dataInputStream = new DataInputStream(clientSocket.getInputStream());
			dataOutputStream = new DataOutputStream(clientSocket.getOutputStream());
			datablock = dataInputStream.readUTF(); //get teamID
			int id = -1;
			try {
				id = Integer.parseInt(datablock);
			} catch (NumberFormatException e) {
				//ignore error, initial id (-1) results in invalid hash
			}
			if (getHash(id) == hash) {
				dataOutputStream.writeUTF("ok - connection established");
				teamID = datablock;
				while (true) {
					datablock = dataInputStream.readUTF();
					if (!datablock.equalsIgnoreCase("")) {
						dataOutputStream.writeUTF("ok");
						System.out.println("data (" + teamID + ") - " + datablock);
						fwFile.write(teamID + ";" + datablock + "\n");
					} else
						break;
				}
			} else {
				dataOutputStream.writeUTF("error - access denied");
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} finally {
			if (clientSocket != null) {
				try {
					clientSocket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (dataInputStream!= null) {
				try {
					dataInputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (dataOutputStream!= null) {
				try {
					dataOutputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fwFile != null) {
				try {
					fwFile.flush();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public int getHash(int i) {
		//negative numbers are used to generate invalid hash (-1)
		if (i < 0) return -1;
		//calculate digit sum
		int z = 0;
		while (i > 9) {
			z = z + (i % 10);
			i = i / 10;
		}
		z = z + i;
		//return digit sum modulo 10
		return z % 10;
	}
}
